﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections;
using MessageServer.utilities;

//This namespace contains the interfaces to be implemented to use the channel
//functionality.
namespace MessageServer.channels
{
    /**
     * Configuration required for the channel.
     * */
    public interface Config
    {
        //attribute that exposes the pipeline creator for clientss
        PipeLineFactory clientpipefactory { get; }
        //Attribute that exposes all the configuration as a properties
        //class.
        Properties options { get; set; }
    }

    /**
     * The Factory that will be used to construct the channel.
     * */
    public interface ChannelFactory
    {
        /**
         * This function should create a channel and return it which will
         * send all it's messages via the pipe passed to this function.
         * */
        Channel createChannel(ChannelPipeline pipe);
    }

    /**
     * This is the main interface the defines the contract of the implementation
     * that should be provided if a channel has to be used.
     * */
    public interface Channel
    {
        Config config { get; set; }                 //Exposes the configuration of this channel
        ChannelPipeline pipeline { get; set; }      //Pipeline through which the events will pass in this channel
        bool connected { get; }                     //true if this channel is connected. Readonly
        bool bound { get; }                         //true if this channel is bound. Readonly
        bool readable { get; set; }                 //if this channel is readable.
        bool writable { get; set; }                 //if this channel is writable.
        EndPoint localaddress { get; }              //local address to which this channel is bound
        EndPoint remoteaddress { get; }             //remote address to which this channel is bound
        Object attachment { get; set; }             //attachment that will be maintained across
        Object customInfo { get; set; }             //information abt the channel attached to this
        int channelid { get; }                      //channelid for debugging

        /**
         * Bind this channel to the given local address. This function
         * should return an eventtracker that can be used to track the progress of
         * this action.
         * */
        EventTracker bind(EndPoint endpoint);

        /**
         * Connect this channel to the given remoteaddress. This function should return
         * the eventracker that can be used to track this action on the channel.
         * */
        EventTracker connect(EndPoint remoteaddr);

        /**
         * Write the given object into the channel. Return the EventTracker object that
         * can be used to track this action on the channel.
         * */
        EventTracker write(Object obj);

        /**
         * Disconnect this channel from the connection currently active. Return the
         * EventTracker object that can be used to track this action.
         * */
        EventTracker disconnect();

        /**
         * Close this channel and return the EventTracker to track this action.
         * */
        EventTracker close();
    }

    /**
     * An AbstractChannel that throws an NoImplemented exception for the required
     * functions. Derive from this class and implement only those actions that are 
     * supported on the channel implemented.
     * */
    public class AbstractChannel : Channel
    {
        Object _attachment;
        Object _customInfo;
        int _channelid;

        public AbstractChannel(int id)
        {
            _channelid = id;
        }

        public virtual Config config
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public virtual ChannelPipeline pipeline
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public virtual bool connected
        {
            get { throw new NotImplementedException(); }
        }

        public virtual bool bound
        {
            get { throw new NotImplementedException(); }
        }

        public virtual bool readable
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public virtual bool writable
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public virtual EndPoint localaddress
        {
            get { throw new NotImplementedException(); }
        }

        public virtual EndPoint remoteaddress
        {
            get { throw new NotImplementedException(); }
        }

        public virtual EventTracker bind(EndPoint endpoint)
        {
            throw new NotImplementedException();
        }

        public virtual EventTracker connect(EndPoint remoteaddr)
        {
            throw new NotImplementedException();
        }

        public virtual EventTracker write(object obj)
        {
            throw new NotImplementedException();
        }

        public virtual EventTracker disconnect()
        {
            throw new NotImplementedException();
        }

        public virtual EventTracker close()
        {
            throw new NotImplementedException();
        }

        public virtual Object attachment { get { return _attachment; } set { _attachment = value; } }
        public virtual Object customInfo { get { return _customInfo; } set { _customInfo = value; } }
        public virtual int channelid { get { return _channelid; } }
    }
}
